package com.tcs.tsrm;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import com.tcs.tsrm.beans.ClusteringThresholds;
import com.tcs.tsrm.beans.PreProcessData;
import com.tcs.tsrm.birch.BirchClustering;

public class RangeMotifDiscovery {

	/**
	 * @param thresholds
	 * @throws URISyntaxException
	 * @throws IOException
	 */
	public void execute(ClusteringThresholds thresholds) throws IOException,
	URISyntaxException {
		System.out.println("Starting Range Motif Discovery...");
		RangeMotifDiscovery runner = new RangeMotifDiscovery();
		runner.runMotifDiscoveryBirch(thresholds);
	}



	/**
	 * @param thresholds
	 * @return birchClusters
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public ArrayList<ArrayList<Integer>> runMotifDiscoveryBirch(
			ClusteringThresholds thresholds) throws IOException,
			URISyntaxException {
		boolean normalization = true;
		ArrayList<ArrayList<Integer>> birchClusters = null;
		try {
			double coinRadius = thresholds.getCoinRadius();
			if (normalization) {
				coinRadius = coinRadius
						* Math.sqrt((double) thresholds.getMotifWidth() / 20);
				thresholds.setCoinRadius(coinRadius);
			}

			long preProcessingStart = System.currentTimeMillis();
			ArrayList<double[]> nonTrivialMatrix = loadNonTrivialMat(thresholds);
			long preProcessingStop = System.currentTimeMillis();
			long preProcessingTime = preProcessingStop - preProcessingStart;	
			System.out.println("Time taken for preprocessing is ->"+preProcessingTime/1000 + " seconds");
			birchClusters = executeClusteringBirch(coinRadius,
					nonTrivialMatrix, preProcessingTime, thresholds);

		} catch (IOException e) {
			System.out.println("Exception: " + e);
		}

		return birchClusters;
	}

	/**
	 * @param thresholds
	 * @return nonTrivialMatrix
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public ArrayList<double[]> loadNonTrivialMat(ClusteringThresholds thresholds)
			throws IOException, URISyntaxException {

		String folderName = thresholds.getDataInputPath();
		PreProcessData dataPreProcessor = new PreProcessData();
		setPreProcessDataThresholds(dataPreProcessor, thresholds);
		ArrayList<double[]> nonTrivialMatrix = dataPreProcessor
				.getNonTrivialMatrix(folderName, thresholds);
		return nonTrivialMatrix;
	}

	/**
	 * @param coinRadius
	 * @param nonTrivialMatrix
	 * @param preProcessingTime
	 * @param thresholds
	 * @return birchClusters
	 * @throws IOException
	 */
	private ArrayList<ArrayList<Integer>> executeClusteringBirch(
			double coinRadius, ArrayList<double[]> nonTrivialMatrix,
			long preProcessingTime, ClusteringThresholds thresholds)
					throws IOException {
		String algo = thresholds.getAlgorithm();
		ArrayList<ArrayList<Integer>> birchClusters = null;
		if (algo.equalsIgnoreCase("birch")) {
			BirchClustering birch = new BirchClustering(nonTrivialMatrix,
					coinRadius, preProcessingTime);
			birchClusters = birch.executeClustering(thresholds);
		} 
		return birchClusters;

	}

	/**
	 * @param dataPreProcessor
	 * @param thresholds
	 * @return dataPreProcessor
	 */
	private PreProcessData setPreProcessDataThresholds(
			PreProcessData dataPreProcessor, ClusteringThresholds thresholds) {
		int reducedDimLen = thresholds.getMotifWidth() / 2;
		thresholds.setReducedDim(reducedDimLen);
		dataPreProcessor.setDataPreProcessingConstants(
				thresholds.getMotifWidth(), reducedDimLen,
				thresholds.getDevFilterThres(), thresholds.getSensorIndex());
		return dataPreProcessor;

	}
}
